package com.yorick.resource.controller;

import com.yorick.common.Result.SimpleFactory.ResultFactory;
import com.yorick.common.error.YorickAssert;
import com.yorick.common.error.YorickException;
import com.yorick.common.util.YorickUtil;
import com.yorick.file.dao.FileMapper;
import com.yorick.file.entity.FileDto;
import com.yorick.file.modal.request.CreateFileRequest;
import com.yorick.file.service.FileService;
import com.yorick.login.dao.LoginMapper;
import com.yorick.account.entity.AccountDto;
import com.yorick.login.enums.Account;
import com.yorick.resource.enums.FileType;
import com.yorick.resource.modal.request.FileDownloadRequest;
import com.yorick.resource.modal.request.FileUploadRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Objects;


@Slf4j
@Controller
@RequestMapping("resource")
public class ResourceController {
    @Resource
    FileMapper fileMapper;
    @Resource
    LoginMapper loginMapper;
    @Resource
    FileService fileService;

    public static final String BASE_PATH = "/usr/local/apache-tomcat-8.5.89/webapps/resources/";//测试路径

    @PostMapping(value = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseBody
    public Map<String, Object> uploadFile(@RequestParam("logFile") MultipartFile uploadFile, FileUploadRequest request, HttpSession session) {
        String filename = uploadFile.getOriginalFilename();
        filename = System.currentTimeMillis() + "&" + filename;
        int aid = Integer.parseInt(session.getAttribute(Account.aid.name()).toString());
        AccountDto accountDto = loginMapper.getAccountByAid(aid);
        long fileSize = fileMapper.sumAccountFileSize(aid);
        YorickAssert.validate(
                accountDto.getFileMaxSize() >= fileSize,
                () -> "0",
                () -> "存储空间不足");


        String fileShowName = isFileExist(1, uploadFile.getOriginalFilename(), request.getParentId());
        try {
            File fold=new File(BASE_PATH+aid);
            if(!fold.exists()){//如果文件夹不存在
                fold.mkdir();//创建文件夹
            }
            File file = new File(BASE_PATH+aid, filename);
            //获取账户文件夹下所有文件Hash值
            Map<String,String> fileHashes = YorickUtil.getFolderFileHashes(BASE_PATH+aid);
            if (!fileHashes.containsKey(request.getFileHash())) {
                //Hash不存在，需要写入文件
                uploadFile.transferTo(file);
            }else{
                //Hash存在，返回对应文件名
                filename = fileHashes.get(request.getFileHash());
            }
            Integer fileTypeCode = FileType.OTHER.getFileTypeCode();
            if (filename.split("\\.").length > 1) {
                int lastIndex = filename.lastIndexOf(".");
                String fileTypeName = filename.substring(lastIndex + 1);
                fileTypeCode = getFileType(fileTypeName);
            }
            CreateFileRequest requestBody = CreateFileRequest.builder()
                    .fileName(fileShowName)
                    .fileSize(uploadFile.getSize())
                    .fileType(fileTypeCode)
                    .fileUrl(filename)
                    .parentId(request.getParentId())
                    .build();
            return fileService.createFile(requestBody, aid);
        } catch (IOException e) {
            e.printStackTrace();
            new YorickException("0",e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            new YorickException("0",e.getMessage());
        }
        return ResultFactory.failure().display();
    }

    @PostMapping(value = "/downloadFile")
    public ResponseEntity<org.springframework.core.io.Resource> downloadFile(@RequestBody FileDownloadRequest requestBody,
            HttpServletRequest request) throws IOException {
        //获取文件详情
        HttpSession session = request.getSession();
        int aid = Integer.parseInt(session.getAttribute(Account.aid.name()).toString());
        FileDto data = FileDto.builder()
                .aid(aid)
                .id(requestBody.getId())
                .build();
        FileDto file = fileMapper.findFileById(data);
        YorickAssert.validate(
                Objects.nonNull(file),
                () -> "0",
                () -> "找不到该文件");

        // 获取文件的路径
        String filePath = BASE_PATH+file.getAid()+"/"+file.getFileUrl();
        URL u = new URL("file:///" + filePath);
        Path path = Paths.get(filePath);
        org.springframework.core.io.Resource resource = new UrlResource(path.toUri());

        // 设置响应的内容类型
        String contentType = "application/octet-stream";

        // 返回响应实体
        if (requestBody.getIsOnline()==0){
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        }else{
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(u.openConnection().getContentType()))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + file.getFileName() + "\"")
                    .body(resource);
        }
    }

    private String isFileExist(int sequence, String orgName, Integer parentId) {
        String newName = orgName;
        if (sequence > 1) {
            if (orgName.split("\\.").length > 1) {
                int lastIndex = orgName.lastIndexOf(".");
                String filehead = orgName.substring(0, lastIndex);
                String filetail = orgName.substring(lastIndex + 1);
                newName = filehead + sequence + "." + filetail;
            } else {
                newName = orgName + sequence;
            }
        }
        FileDto data = FileDto.builder()
                .fileName(newName)
                .parentId(parentId)
                .build();
        Integer isFileExist = fileMapper.isFileExist(data);
        if (isFileExist != 0) {
            sequence++;
           return isFileExist(sequence, orgName, parentId);
        }
        return newName;
    }

    private Integer getFileType(String fileTypeName) {
        fileTypeName = fileTypeName.toLowerCase();
        switch (FileType.getByValue(fileTypeName)) {
            case JPG:
            case JPEG:
            case PNG:
            case GIF:
                return FileType.JPG.getFileTypeCode();
            case MP4:
            case MOV:
            case AVI:
            case FLV:
            case WMV:
                return FileType.MP4.getFileTypeCode();
            case FOLDER:
                return FileType.FOLDER.getFileTypeCode();
            case ZIP:
            case RAR:
                return FileType.ZIP.getFileTypeCode();
            case MP3:
            case WMA:
            case AAC:
            case FLAC:
                return FileType.MP3.getFileTypeCode();
            case TXT:
            case SQL:
                return FileType.TXT.getFileTypeCode();
            case OTHER:
            default:
                return FileType.OTHER.getFileTypeCode();
        }
    }
}


